/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simulation;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import logging.LogSetup;
import org.apache.log4j.Logger;
import persistence.DataReader;

/**
 *
 * @author Danielondon
 */
public class DrivingPatternFactory {
    private static Logger logger = LogSetup.getLogger();
    public static Map<String, DrivingPattern> drivingPatterns = new HashMap<String, DrivingPattern>();
    public static String defaultName = "wellbehaved.csv";
    public static int INDEX_STATE = 1;
    public static int INDEX_KILOMETERS = 2;
    private static String WILDCARD_MATLAB = "#";
    public static DrivingPattern createDrivingPattern(String fileName, int slotCount, int slotSize) throws Exception{
        String key = fileName + slotCount;
        if (!drivingPatterns.containsKey(key)){
            try {
                DataReader dataReader = new DataReader(fileName);
                List<String[]> data = dataReader.getData();
                
                if (data.size() == 0)
                    throw new Exception("File is empty.");
                
                String wildCard = data.get(0)[0];
                DrivingPattern pattern;
                if (wildCard.equals(WILDCARD_MATLAB)){
                    // Matlab Format
                    pattern = getDrivingPatternFromMatlabFormat(fileName, data, slotCount, slotSize);
                } else {
                    // Custom Format
                    pattern = getDrivingPatternFromCustomFormat(fileName, data, slotCount, slotSize);
                }
                
                drivingPatterns.put(key, pattern);
            } catch (Exception ex) {
                logger.error(ex);
                throw ex;
            }
        }
        
        return drivingPatterns.get(key);
    }

    private static DrivingPattern getDrivingPatternFromCustomFormat(String name, List<String[]> data, int slotCount, int slotSize) throws Exception {
        
        if (data.size() < slotCount){
            throw new Exception("There is not enough data to build the slots demanded.");
        }

        //Map<Integer, CarState> slotsInfo = new HashMap<Integer, CarState>();
        double kilometers;
        int state;
        int [] isConnected = new int[slotCount];
        double []kilometersRunning = new double[slotCount]; 

        for (int i=0; i < slotCount; i++){
            String [] tokens = data.get(i);
            state = Integer.parseInt(tokens[INDEX_STATE]);
            kilometers = Double.parseDouble(tokens[INDEX_KILOMETERS]);
            CarState carState = CarState.fromInteger(state);
            //slotsInfo.put(i, carState);                    
            isConnected[i] = carState.ordinal();
            kilometersRunning[i] = kilometers;      
        }

        DrivingPattern pattern = new DrivingPattern(name, isConnected, kilometersRunning, slotCount, slotSize);

        return pattern;
    }

    private static DrivingPattern getDrivingPatternFromMatlabFormat(String name, List<String[]> data, int slotCount, int slotSize) throws Exception {
        if (data.size() < 2) {
            throw new Exception("Data has not connected information or requited energy");
        }
        
        String [] connectedRawData = data.get(1);
        String [] requiredRawData = data.get(2);
        
        double energy;
        int state;
        int [] isConnected = new int[slotCount];
        double []energyRequired = new double[requiredRawData.length]; 
        for (int i=0; i < slotCount; i++){
            //logger.info("Connected " + i + " = " + connectedRawData[i]);
            state = Integer.parseInt(connectedRawData[i]);
            CarState carState = CarState.fromInteger(state);
            isConnected[i] = carState.ordinal();
        }
        
        for (int i=0; i < requiredRawData.length; i++){
            //logger.info("Connected " + i + " = " + requiredRawData[i]);
            energy = Double.parseDouble(requiredRawData[i]);
            energyRequired[i] = energy;
        }
            
        DrivingPattern pattern = new DrivingPattern(name, isConnected, slotCount, energyRequired, slotSize);        
        return pattern;
    }
}
